﻿using System;
using System.Collections.Generic;

namespace DCT.CodeBox.Utility
{
    /// <summary>
    /// 实例创建器
    /// </summary>
    public static class InstanceCreator
    {
        /// <summary>
        /// 创建实例委托
        /// </summary>
        /// <param name="tag">标记</param>
        /// <param name="args">初始化参数</param>
        /// <returns></returns>
        public delegate object CreateInstanceHandler(string tag, object[] args);
        
        /// <summary>
        /// 单例实例存储
        /// </summary>
        private static Dictionary<Type, object> singletonInstances = new Dictionary<Type, object>();
        /// <summary>
        /// 类型和创建实例映射
        /// </summary>
        private static Dictionary<Type, CreateInstanceHandler> mappers = new Dictionary<Type, CreateInstanceHandler>();

        /// <summary>
        /// 注册类型
        /// </summary>
        /// <param name="type">类型（一般为接口类型）</param>
        /// <param name="handler">创建实例</param>
        public static void RegisterMapper(Type type, CreateInstanceHandler handler)
        {
            mappers[type] = handler;
        }

        /// <summary>
        /// 移除类型
        /// </summary>
        /// <param name="type">类型（一般为接口类型）</param>
        public static bool UnregisterMapper(Type type)
        {
            return mappers.Remove(type);
        }

        /// <summary>
        /// 清除所有类型映射
        /// </summary>
        public static void ClearMapper() {
            mappers.Clear();
        }

        /// <summary>
        /// 移除单例
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static bool RemoveSingleton(Type type) {
            return singletonInstances.Remove(type);
        }

        /// <summary>
        /// 清除所有单例
        /// </summary>
        public static void ClearSingleton() {
            singletonInstances.Clear();
        }

        /// <summary>
        /// 是否存在类型映射
        /// </summary>
        /// <param name="type">类型（一般为接口类型）</param>
        /// <returns></returns>
        public static bool ExistMapper(Type type)
        {
            return mappers.ContainsKey(type);
        }

        /// <summary>
        /// 创建实例
        /// </summary>
        /// <typeparam name="T">需要创建的类型</typeparam>
        /// <returns></returns>
        public static T Create<T>()
        {
            return Create<T>(null, null);
        }

        /// <summary>
        /// 创建实例
        /// </summary>
        /// <typeparam name="T">需要创建的类型</typeparam>
        /// <param name="tag">标记</param>
        /// <param name="args">初始化参数</param>
        /// <returns></returns>
        public static T Create<T>(string tag, object[] args)
        {
            Type targetType = typeof(T);
            T instance = default(T);

            if (ExistMapper(typeof(T)))
            {
                instance = (T)mappers[targetType](tag, args);
            }
            return instance;
        }

        /// <summary>
        /// 创建单例
        /// </summary>
        /// <typeparam name="T">需要创建的类型</typeparam>
        /// <returns></returns>
        public static T CreateSingleton<T>()
        {
            return CreateSingleton<T>(null, null);
        }

        /// <summary>
        /// 创建单例实例
        /// </summary>
        /// <typeparam name="T">需要创建的类型</typeparam>
        /// <param name="tag">标记</param>
        /// <param name="args">初始化参数</param>
        /// <returns></returns>
        public static T CreateSingleton<T>(string tag, object[] args) {
            Type targetType = typeof(T);
            if(!singletonInstances.ContainsKey(targetType)){
                return (T)singletonInstances[targetType];
            }

            T instance = Create<T>(tag, args);
            if (!default(T).Equals(instance)) {
                singletonInstances[targetType] = instance;
            }

            return instance;
        }

        /// <summary>
        /// 无参构造函数构造器
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static CreateInstanceHandler GetDefaultEmptyCtorHandler<T>()
            where T : new()
        {
            return new CreateInstanceHandler(delegate
            {
                return new T();
            });
        }
    }
}
